package org.sjs.dreamfly.browser

import android.content.Context
import android.graphics.Bitmap
import android.net.http.SslError
import android.os.Message
import android.view.KeyEvent
import android.webkit.ClientCertRequest
import android.webkit.HttpAuthHandler
import android.webkit.RenderProcessGoneDetail
import android.webkit.SafeBrowsingResponse
import android.webkit.SslErrorHandler
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
import org.sjs.dreamfly.browser.jsbridge.JsInjector
import org.sjs.dreamfly.browser.jsbridge.JsInjector.executeJsMethod
import org.sjs.dreamfly.browser.jsbridge.JsInjector.hasPoint
import org.sjs.dreamfly.common.base.ListenerOwner
import org.sjs.dreamfly.common.util.LogUtil
import java.lang.ref.WeakReference

class PhemonWebViewClient(val context: Context,
                          private val injectStrategy: JsInjector.InjectStrategy?)
    : WebViewClient(), ListenerOwner<JsInjector.InjectEventListener> {

    private val logDisabled = true
    
    private var visitor: WebViewClient? = null
    fun <T: WebViewClient> accept(visitor: T) {
        this.visitor = visitor
    }

    override val listeners: MutableList<WeakReference<JsInjector.InjectEventListener>> by lazy {
        mutableListOf()
    }
    override fun shouldOverrideUrlLoading(
        view: WebView?,
        request: WebResourceRequest?
    ): Boolean {
        LogUtil.d("url:${request?.url}", logDisabled)
        return visitor?.shouldOverrideUrlLoading(view, request)?:
        super.shouldOverrideUrlLoading(view, request)
    }

    override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
        LogUtil.d("url:$url", logDisabled)
        val method = injectStrategy?.getMethods()?:0
        val point = injectStrategy?.getPoints()?:0
        if (JsInjector.hasPoint(point, BrowserConst.InjectPoint.POINT_ON_PAGE_START)) {
            url?.let {
                executeJsMethod(context, it, view!!, method)
                notifyListeners(url, BrowserConst.InjectPoint.POINT_ON_PAGE_START, method)
            }
        }
    }

    override fun onPageFinished(view: WebView?, url: String?) {
        LogUtil.d("url:$url", logDisabled)
        val method = injectStrategy?.getMethods()?:0
        val point = injectStrategy?.getPoints()?:0
        visitor?.onPageFinished(view, url)
        if (JsInjector.hasPoint(point, BrowserConst.InjectPoint.POINT_ON_PAGE_FINISH)) {
            url?.let {
                view?.postDelayed({
                    executeJsMethod(context, it, view, method)
                    notifyListeners(url, BrowserConst.InjectPoint.POINT_ON_PAGE_FINISH, method)}, 100)
            }
        }
    }

    override fun onReceivedSslError(
        view: WebView?,
        handler: SslErrorHandler?,
        error: SslError?
    ) {
        LogUtil.d("${error?.url}", logDisabled)
        super.onReceivedSslError(view, handler, error)
    }

    override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
        LogUtil.d("$url", logDisabled)
        return super.shouldOverrideUrlLoading(view, url)
    }

    override fun onLoadResource(view: WebView?, url: String?) {
        LogUtil.d("url:$url, originUrl:${view?.originalUrl}", logDisabled)
        visitor?.onLoadResource(view, url)
        super.onLoadResource(view, url)
    }

    override fun onPageCommitVisible(view: WebView?, url: String?) {
        LogUtil.d("$url", logDisabled)
        super.onPageCommitVisible(view, url)
    }

    override fun shouldInterceptRequest(view: WebView?, url: String?): WebResourceResponse? {
        LogUtil.d("$url", logDisabled)
        return super.shouldInterceptRequest(view, url)
    }

    override fun shouldInterceptRequest(
        view: WebView?,
        request: WebResourceRequest?
    ): WebResourceResponse? {
        LogUtil.d("${request?.url}", logDisabled)
        return super.shouldInterceptRequest(view, request)
    }

    override fun onTooManyRedirects(view: WebView?, cancelMsg: Message?, continueMsg: Message?) {
        LogUtil.d("cancelMsg:$cancelMsg, continueMsg:$continueMsg", logDisabled)
        super.onTooManyRedirects(view, cancelMsg, continueMsg)
    }

    override fun onReceivedError(
        view: WebView?,
        errorCode: Int,
        description: String?,
        failingUrl: String?
    ) {
        LogUtil.d("errorCode:$errorCode, description:$description, failingUrl:$failingUrl", logDisabled)
        if (errorCode == ERROR_HOST_LOOKUP) {
            view?.loadUrl("file:///android_asset/error.html")
        }
        super.onReceivedError(view, errorCode, description, failingUrl)
    }

    override fun onReceivedError(
        view: WebView?,
        request: WebResourceRequest?,
        error: WebResourceError?
    ) {
        LogUtil.d("${request?.url}, error:$error", logDisabled)
        super.onReceivedError(view, request, error)
    }

    override fun onReceivedHttpError(
        view: WebView?,
        request: WebResourceRequest?,
        errorResponse: WebResourceResponse?
    ) {
        LogUtil.d("${request?.url}, error:${errorResponse}", logDisabled)
        super.onReceivedHttpError(view, request, errorResponse)
    }

    override fun onFormResubmission(view: WebView?, dontResend: Message?, resend: Message?) {
        LogUtil.d("dontResend:$dontResend, resend:$resend", logDisabled)
        super.onFormResubmission(view, dontResend, resend)
    }

    override fun doUpdateVisitedHistory(view: WebView?, url: String?, isReload: Boolean) {
        LogUtil.d("$url, isReload:$isReload", logDisabled)
        super.doUpdateVisitedHistory(view, url, isReload)
    }

    override fun onReceivedClientCertRequest(view: WebView?, request: ClientCertRequest?) {
        LogUtil.d(ignore = logDisabled)
        super.onReceivedClientCertRequest(view, request)
    }

    override fun onReceivedHttpAuthRequest(
        view: WebView?,
        handler: HttpAuthHandler?,
        host: String?,
        realm: String?
    ) {
        LogUtil.d("host:$host, realm:$realm", logDisabled)
        super.onReceivedHttpAuthRequest(view, handler, host, realm)
    }

    override fun shouldOverrideKeyEvent(view: WebView?, event: KeyEvent?): Boolean {
        LogUtil.d(ignore = logDisabled)
        return super.shouldOverrideKeyEvent(view, event)
    }

    override fun onUnhandledKeyEvent(view: WebView?, event: KeyEvent?) {
        LogUtil.d(ignore = logDisabled)
        super.onUnhandledKeyEvent(view, event)
    }

    override fun onScaleChanged(view: WebView?, oldScale: Float, newScale: Float) {
        LogUtil.d(ignore = logDisabled)
        super.onScaleChanged(view, oldScale, newScale)
    }

    override fun onReceivedLoginRequest(
        view: WebView?,
        realm: String?,
        account: String?,
        args: String?
    ) {
        LogUtil.d("realm:$realm, account:$account, args:$args", logDisabled)
        super.onReceivedLoginRequest(view, realm, account, args)
    }

    override fun onRenderProcessGone(view: WebView?, detail: RenderProcessGoneDetail?): Boolean {
        LogUtil.d(ignore = logDisabled)
        return super.onRenderProcessGone(view, detail)
    }

    override fun onSafeBrowsingHit(
        view: WebView?,
        request: WebResourceRequest?,
        threatType: Int,
        callback: SafeBrowsingResponse?
    ) {
        LogUtil.d(ignore = logDisabled)
        super.onSafeBrowsingHit(view, request, threatType, callback)
    }
}